import {Scene ,PerspectiveCamera, HemisphereLight, Clock,DirectionalLight,WebGLRenderer, Color,
     PMREMGenerator,sRGBEncoding, AnimationMixer   } from '../libs/three137/three.module.js';
import { GLTFLoader } from '../libs/three137/GLTFLoader.js';
import { DRACOLoader } from '../libs/three137/DRACOLoader.js';
import { RGBELoader } from '../libs/three137/RGBELoader.js';
import { OrbitControls } from '../libs/three137/OrbitControls.js';
import { LoadingBar } from '../libs/LoadingBar.js';
import { urls} from '../assets/store.js'

const { floor, random,  } = Math;
/**  主要是动画之间的切换 随机 */
class Game{
	constructor(){
		const container = document.createElement( 'div' );
		document.body.appendChild( container );
        
		this.clock = new Clock();

        this.loadingBar = new LoadingBar();
        this.loadingBar.visible = false;

	
        
		this.camera = new PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 50 );
		this.camera.position.set( 1, 1.7, 2.8 );
        
		let col = 0x605550;
		this.scene = new Scene();
		this.scene.background = new Color( col );
		
		const ambient = new HemisphereLight(0xffffff, 0xbbbbff, 1);
		this.scene.add(ambient);

        const light = new DirectionalLight();
        light.position.set( 0.2, 1, 1 );
			
		this.renderer = new WebGLRenderer({ antialias: true, alpha: true } );
		this.renderer.setPixelRatio( window.devicePixelRatio );
		this.renderer.setSize( window.innerWidth, window.innerHeight );
        this.renderer.outputEncoding = sRGBEncoding;
		container.appendChild( this.renderer.domElement );
        this.setEnvironment();
        
        const controls = new OrbitControls( this.camera, this.renderer.domElement );
        controls.target.set(0, 1, 0);
		controls.update();

        this.loadEve();
		
		window.addEventListener('resize', this.resize.bind(this) );
        
	}
	
    resize(){
        this.camera.aspect = window.innerWidth / window.innerHeight;
    	this.camera.updateProjectionMatrix();
    	this.renderer.setSize( window.innerWidth, window.innerHeight ); 
    }
    
    setEnvironment(){
        const loader = new RGBELoader();
        const pmremGenerator = new PMREMGenerator( this.renderer );
        pmremGenerator.compileEquirectangularShader();
        
        const self = this;
        
        loader.load( urls.factory_hdr, ( texture ) => {
          const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
          pmremGenerator.dispose();

          self.scene.environment = envMap;

        }, undefined, (err)=>{
            console.error( err.message );
        } );
    }

    loadEve(){
        const dracoLoader = new DRACOLoader()
        dracoLoader.setDecoderPath('../libs/three137/draco/') ;
        const loader  = new GLTFLoader();
        loader.setDRACOLoader(dracoLoader);
        this.loadingBar.visible = true ;
        loader.load( urls.eve_glb, 
            gltf => { 
                this.loadingBar.visible =false ;
                this.scene.add(gltf.scene)
                this.eve = gltf.scene;
                this.mixer  = new AnimationMixer(this.eve) ;
                console.log(gltf);
    
                this.animations ={} ;
                gltf.animations.forEach((animation)=> {
                    this.animations[animation.name.toLowerCase()] = animation
                })
                let n = this.eve.animations.length ;
                this.newAnim()
                
            },
            xhr => { 
                this.loadingBar.progress = xhr.loaded/ xhr.total
            },

            err=> console.warn(err)
            )
    	
	}			
    
	newAnim(){
		// 每隔一段时间 随机播放另一种动画
        let  keys = Reflect.ownKeys(this.animations), index=0;
        do { 
            index  = floor( random()* keys.length)
        }while( keys[index] === this.actionName )

        this.action = keys[index];
        console.log(keys[index]);
        setTimeout(() => {
           this.newAnim() 
        }, 3000);
	}

	set action(name){
        let key = name.toLowerCase();
		if(this.actionName === key) return ;

        //播放单个 动画使用 mixer.clipAction 拎出来
        let clip =this.animations[key] ;

        if(clip){ 
            let action = this.mixer.clipAction(clip) ;

            action.reset() ;
            this.actionName = key ;

            action.play();// 这个到底应放在前面还是后面
            //要关掉上一个动画 不然会叠在一起
            if(this.curAction){ 
                // action duration wrap 在传入的时间段内, 让此动作淡出（fade out），同时让另一个动作淡入
                this.curAction.crossFadeTo(action, .5,)
            }

            this.curAction = action ;

        }
			// return Reflect.set(this, 'action', name)

	}
    // 设置了捕获器 这个属性就不可能有自己的值了，只能是个代理
	// get action(){ return Reflect.get(this,'action') }


	render() {
		const dt = this.clock.getDelta();
        // 播放动画还需要手动更新mixer
        if(this.mixer) this.mixer.update(dt)
        this.renderer.render( this.scene, this.camera );
    }
}

export { Game };